package hibernate;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import controller.Index;
import pojo.Products;
import dao.ProductsDAO;
@Repository("ProductsDAO")
public class HibernateProductsDAO implements ProductsDAO {

	private static final Logger logger = Logger.getLogger(HibernateProductsDAO.class);
	private SessionFactory sessionFactory;
	
	@Autowired
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}
	@Transactional
	public Products getProduct(String productid) {
		Session session = sessionFactory.getCurrentSession();
        Products p = null;
        String hql =String.format("from Products p where p.productid ='%s'",productid);
       
        Query query = session.createQuery(hql);
        
        List<Products> ds = query.list();
        if(ds.size() == 1)
            p = ds.get(0);
        return p;
	}
	@Transactional
	public List<Products> getProductList() {
		Query query = sessionFactory.getCurrentSession().createQuery("from Products");
		return query.list();
	}
	@Transactional
	public List<String> Search(String productname) {
		String hql = String.format("from Products p where p.productname = '%s'",productname);
		Query query = sessionFactory.getCurrentSession().createQuery(hql);
		return query.list();
	}
	
	@Transactional
	public List<Products> Search(String productname,String productcatalog,String[] brand,String[] condition,String rating,String minprice,String maxprice,int page,int productonpage, int sortby)
	{
		Products sp = null;
        String hql =String.format("from Products p where 1=1 ");
        if(productname.trim().equals("") == false)
            hql = hql + " and p.productname like '%"+productname+"%' ";
        if(productcatalog.equals("-1")==false){
            hql = hql +" and p.productcatalog.catalogid="+productcatalog;
        }
        if(brand != null)
        {	
        	List<String> brands = Arrays.asList(brand);
            hql += " and (p.brand.brandname =";
            for(int i = 0; i< brands.size() - 1;i++)
            {
            	hql+="'"+brands.get(i)+"'"+" or p.brand.brandname =";
            }
            hql+= "'"+brands.get(brands.size()-1)+"'" +")";
        
        }
        if(condition != null)
        {
        	List<String>conditions = Arrays.asList(condition);
            hql += " and (p.condition.conditionname =";
            for(int i = 0; i< conditions.size() - 1;i++)
            {
            	hql+="'"+conditions.get(i)+"'"+" or p.condition.conditionname =";
            }
            hql+= "'"+conditions.get(conditions.size()-1)+"'" +")";
        }
        if(rating.equals("-1") == false)
    	  hql = hql+ " and p.rating >"+rating;
        if(minprice != "")
        	hql += " and p.price >"+ minprice;
        if(maxprice !="")
        	hql += " and p.price <" +maxprice;
        hql = addHqlSort(sortby, hql);
        int n = (page-1)*productonpage;
        int m = productonpage;
        Query query = sessionFactory.getCurrentSession().createQuery(hql);
        if(productonpage != -1){
            query.setFirstResult(n);
            query.setMaxResults(m);
        }
        List<Products> ds = query.list();
        
        return ds;
		
	}
	
	@Transactional
	public List<Products> getProductList(String productcatalogid) {
		Session session = sessionFactory.getCurrentSession();
		String hql = "from Products p where p.productcatalog.catalogid = '" + productcatalogid +"'";
		Query query = session.createQuery(hql);
		List<Products> ds = query.list();
		return ds;
	}
	@Transactional
	public boolean updateRating(int averagerating, String productid) {
		try
        {
		Session session = sessionFactory.getCurrentSession();
		String hql = "update Products set rating = " + averagerating + " where productid =" + productid;
		Query query = session.createQuery(hql);
		query.executeUpdate();
		logger.info("Update rating completed");
		return true;
        }catch(HibernateException e)
        {
        	logger.error("Update rating got Error, this is it :",e);
        }
        return false;
	}
//	@Transactional
//	public String Compare4 (String spec1, String spec2,String spec3,String spec4)
//	{
//		String[] s1 = spec1.split("@");
//		String[] s2 = spec2.split("@");
//		String[] s3 = spec3.split("@");
//		String[] s4 = spec4.split("@");
//		String temp ;
//		List<String> name1 = new ArrayList<String>();
//		List<String> details1 = new ArrayList<String>();
//		List<String> name2 = new ArrayList<String>();
//		List<String> details2 = new ArrayList<String>();
//		List<String> name3 = new ArrayList<String>();
//		List<String> details3 = new ArrayList<String>();
//		List<String> name4 = new ArrayList<String>();
//		List<String> details4 = new ArrayList<String>();
//		
//		for(int i = 0; i < s1.length; i++)
//		{
//			temp = s1[i].split(":")[0];
//			name1.add(temp);
//			temp = s1[i].split(":")[1];
//			details1.add(temp);
//		}
//		for(int i = 0; i < s2.length; i++)
//		{
//			temp = s2[i].split(":")[0];
//			name2.add(temp);
//			temp = s2[i].split(":")[1];
//			details2.add(temp);
//		}
//		for(int i = 0; i < s3.length; i++)
//		{
//			temp = s3[i].split(":")[0];
//			name3.add(temp);
//			temp = s3[i].split(":")[1];
//			details3.add(temp);
//		}
//		for(int i = 0; i < s4.length; i++)
//		{
//			temp = s4[i].split(":")[0];
//			name4.add(temp);
//			temp = s4[i].split(":")[1];
//			details4.add(temp);
//		}
//		String compare= "";
//		List<String> namefinal = new ArrayList<String>();
//		for(int i=0 ;i<name1.size();i++)
//		{
//			namefinal.add(name1.get(i));
//		}
//		List<String> detailsfinal1 = new ArrayList<String>();
//		List<String> detailsfinal2 = new ArrayList<String>();
//		List<String> detailsfinal3 =new ArrayList<String>();
//		List<String> detailsfinal4 = new ArrayList<String>();
//		for(int i=0;i<name2.size();i++)
//		{
//			if(!namefinal.contains(name2.get(i)))
//				namefinal.add(name2.get(i));
//		}
//		for(int i=0;i<name3.size();i++)
//		{
//			if(!namefinal.contains(name3.get(i)))
//				namefinal.add(name3.get(i));
//		}
//		for(int i=0;i<name4.size();i++)
//		{
//			if(!namefinal.contains(name4.get(i)))
//				namefinal.add(name4.get(i));
//		}
//		boolean add = false;
//		for(int i= 0 ;i < namefinal.size();i++)
//		{
//			add = false;
//			for(int j=0; j< name1.size();j++)
//			{
//				
//				if(name1.get(j).equals(namefinal.get(i)))
//				{
//				detailsfinal1.add(details1.get(j));		
//				add = true;
//				}
//			}
//			if(add == false)
//				detailsfinal1.add("No");
//		}
//		for(int i= 0 ;i < namefinal.size();i++)
//		{
//			add = false;
//			for(int j=0; j< name2.size();j++)
//			{
//				
//				if(name2.get(j).equals(namefinal.get(i)))
//				{
//				detailsfinal2.add(details2.get(j));		
//				add = true;
//				}
//			}
//			if(add == false)
//				detailsfinal2.add("No");
//		}
//		for(int i= 0 ;i < namefinal.size();i++)
//		{
//			add = false;
//			for(int j=0; j< name3.size();j++)
//			{
//				if(name3.get(j).equals(namefinal.get(i)))
//				{
//				detailsfinal3.add(details3.get(j));		
//				add = true;
//				}
//			}
//			if(add == false)
//				detailsfinal3.add("No");
//		}
//		for(int i= 0 ;i < namefinal.size();i++)
//		{
//			add = false;
//			for(int j=0; j< name4.size();j++)
//			{
//				
//				if(name4.get(j).equals(namefinal.get(i)))
//				{
//				detailsfinal4.add(details4.get(j));		
//				add = true;
//				}
//			}
//			if(add == false)
//				detailsfinal4.add("No");
//		}
//		
//		for(int i = 0; i< namefinal.size();i++)
//		{
//			
//			compare += namefinal.get(i)+":";
//			compare += detailsfinal1.get(i)+":";
//			compare += detailsfinal2.get(i)+":";
//			compare += detailsfinal3.get(i)+":";
//			compare += detailsfinal4.get(i)+":";
//			if(i != namefinal.size())
//			compare+= "@";
//		}
//		return compare;
//	}
//	//Compare 2
//	@Transactional
//	public String Compare2 (String spec1, String spec2)
//	{
//		String[] s1 = spec1.split("@");
//		String[] s2 = spec2.split("@");
//		String temp ;
//		List<String> name1 = new ArrayList<String>();
//		List<String> details1 = new ArrayList<String>();
//		List<String> name2 = new ArrayList<String>();
//		List<String> details2 = new ArrayList<String>();
//		
//		for(int i = 0; i < s1.length; i++)
//		{
//			temp = s1[i].split(":")[0];
//			name1.add(temp);
//			temp = s1[i].split(":")[1];
//			details1.add(temp);
//		}
//		for(int i = 0; i < s2.length; i++)
//		{
//			temp = s2[i].split(":")[0];
//			name2.add(temp);
//			temp = s2[i].split(":")[1];
//			details2.add(temp);
//		}
//		String compare= "";
//		List<String> namefinal = new ArrayList<String>();
//		for(int i=0 ;i<name1.size();i++)
//		{
//			namefinal.add(name1.get(i));
//		}
//		List<String> detailsfinal1 = new ArrayList<String>();
//		List<String> detailsfinal2 = new ArrayList<String>();
//		for(int i=0;i<name2.size();i++)
//		{
//			if(!namefinal.contains(name2.get(i)))
//				namefinal.add(name2.get(i));
//		}
//		boolean add = false;
//		for(int i= 0 ;i < namefinal.size();i++)
//		{
//			add = false;
//			for(int j=0; j< name1.size();j++)
//			{
//				
//				if(name1.get(j).equals(namefinal.get(i)))
//				{
//				detailsfinal1.add(details1.get(j));		
//				add = true;
//				}
//			}
//			if(add == false)
//				detailsfinal1.add("No");
//		}
//		for(int i= 0 ;i < namefinal.size();i++)
//		{
//			add = false;
//			for(int j=0; j< name2.size();j++)
//			{
//				
//				if(name2.get(j).equals(namefinal.get(i)))
//				{
//				detailsfinal2.add(details2.get(j));		
//				add = true;
//				}
//			}
//			if(add == false)
//				detailsfinal2.add("No");
//		}
//		
//		
//		for(int i = 0; i< namefinal.size();i++)
//		{
//			
//			compare += namefinal.get(i)+":";
//			compare += detailsfinal1.get(i)+":";
//			compare += detailsfinal2.get(i)+":";
//			if(i != namefinal.size())
//			compare+= "@";
//		}
//		return compare;
//	}
//	// Compare 3
//	@Transactional
//	public String Compare3 (String spec1, String spec2,String spec3)
//	{
//		String[] s1 = spec1.split("@");
//		String[] s2 = spec2.split("@");
//		String[] s3 = spec3.split("@");
//		
//		String temp ;
//		List<String> name1 = new ArrayList<String>();
//		List<String> details1 = new ArrayList<String>();
//		List<String> name2 = new ArrayList<String>();
//		List<String> details2 = new ArrayList<String>();
//		List<String> name3 = new ArrayList<String>();
//		List<String> details3 = new ArrayList<String>();
//		
//		for(int i = 0; i < s1.length; i++)
//		{
//			temp = s1[i].split(":")[0];
//			name1.add(temp);
//			temp = s1[i].split(":")[1];
//			details1.add(temp);
//		}
//		for(int i = 0; i < s2.length; i++)
//		{
//			temp = s2[i].split(":")[0];
//			name2.add(temp);
//			temp = s2[i].split(":")[1];
//			details2.add(temp);
//		}
//		for(int i = 0; i < s3.length; i++)
//		{
//			temp = s3[i].split(":")[0];
//			name3.add(temp);
//			temp = s3[i].split(":")[1];
//			details3.add(temp);
//		}
//		String compare= "";
//		List<String> namefinal = new ArrayList<String>();
//		for(int i=0 ;i<name1.size();i++)
//		{
//			namefinal.add(name1.get(i));
//		}
//		List<String> detailsfinal1 = new ArrayList<String>();
//		List<String> detailsfinal2 = new ArrayList<String>();
//		List<String> detailsfinal3 = new ArrayList<String>();
//		for(int i=0;i<name2.size();i++)
//		{
//			if(!namefinal.contains(name2.get(i)))
//				namefinal.add(name2.get(i));
//		}
//		for(int i=0;i<name3.size();i++)
//		{
//			if(!namefinal.contains(name3.get(i)))
//				namefinal.add(name3.get(i));
//		}
//		boolean add = false;
//		for(int i= 0 ;i < namefinal.size();i++)
//		{
//			add = false;
//			for(int j=0; j< name1.size();j++)
//			{
//				
//				if(name1.get(j).equals(namefinal.get(i)))
//				{
//				detailsfinal1.add(details1.get(j));		
//				add = true;
//				}
//			}
//			if(add == false)
//				detailsfinal1.add("No");
//		}
//		for(int i= 0 ;i < namefinal.size();i++)
//		{
//			add = false;
//			for(int j=0; j< name2.size();j++)
//			{
//				
//				if(name2.get(j).equals(namefinal.get(i)))
//				{
//				detailsfinal2.add(details2.get(j));		
//				add = true;
//				}
//			}
//			if(add == false)
//				detailsfinal2.add("No");
//		}
//		for(int i= 0 ;i < namefinal.size();i++)
//		{
//			add = false;
//			for(int j=0; j< name3.size();j++)
//			{
//				if(name3.get(j).equals(namefinal.get(i)))
//				{
//				detailsfinal3.add(details3.get(j));		
//				add = true;
//				}
//			}
//			if(add == false)
//				detailsfinal3.add("No");
//		}
//		
//		for(int i = 0; i< namefinal.size();i++)
//		{
//			
//			compare += namefinal.get(i)+":";
//			compare += detailsfinal1.get(i)+":";
//			compare += detailsfinal2.get(i)+":";
//			compare += detailsfinal3.get(i)+":";
//			if(i != namefinal.size())
//			compare+= "@";
//		}
//		return compare;
//	}
	
	@Transactional
	public String CompareGeneral(String[] specs)
	{
		int count = specs.length;
		List<String[]> s = new ArrayList<String[]>();
		String temp;
		String compare = "";
		List<List<String>> name  = 	new ArrayList<List<String>>();
		List<List<String>> details  = new ArrayList<List<String>>();
		List<List<String>> detailsfinal  = new ArrayList<List<String>>();
		List<String> namefinal = new ArrayList<String>();
		boolean add = false;
		for(int i = 0;i< count;i++)
		{
			s.add(specs[i].split("@"));
		}
		for(int i = 0; i < count;i++)
		{
			name.add(new ArrayList<String>());
			details.add(new ArrayList<String>());
			for(int j = 0; j < s.get(i).length;j++)
			{
				temp = s.get(i)[j].split(":")[0];
				
				name.get(i).add(temp);
				
				temp = s.get(i)[j].split(":")[1];
				
				details.get(i).add(temp);
			}
		}
		for(int i=0 ;i<name.get(0).size();i++)
		{
			namefinal.add(name.get(0).get(i));
		}
		for(int i = 1; i < count;i++)
		{
			for(int j = 0 ;j<name.get(i).size();j++)
			{
				if(!namefinal.contains(name.get(i).get(j)))
					namefinal.add(name.get(i).get(j));
			}
		}
		for(int k= 0 ;k < count;k++)
		{
			detailsfinal.add(new ArrayList<String>());
			for(int i= 0 ;i < namefinal.size();i++)
			{
				add = false;
				for(int j=0; j< name.get(k).size();j++)
				{
					if(name.get(k).get(j).equals(namefinal.get(i)))
					{
					detailsfinal.get(k).add(details.get(k).get(j));		
					add = true;
					}
				}
				if(add == false)
					detailsfinal.get(k).add("No");
			}
		}
		for(int k = 0;k <namefinal.size();k++)
		{
			compare += namefinal.get(k)+":";
			for(int i = 0; i< count;i++)
			{
				compare += detailsfinal.get(i).get(k)+":";
				
			}
			if(k != namefinal.size())
				compare+= "@";
		}
		return compare;
	}
	
	
	
	@Transactional
	public boolean updatetodatabase(Products d1,int quantity4sell)
	{
		if(quantity4sell > d1.getQuantity())
			return false;
		else
		{
			int quantitynew = d1.getQuantity()- quantity4sell;
			String hql = "update Products set quantity = "+quantitynew+" where productid = "+d1.getProductid();
			try
			{
			Query query = sessionFactory.getCurrentSession().createQuery(hql);
			query.executeUpdate();
			logger.info("Update quantity of product done");
			return true;
			}
			catch(Exception e)
			{
				e.printStackTrace();
				logger.error("Update quantity of product failed,error :",e);
			}
		}
		return false;
	}
	@Transactional
	public int pagecount(String id, int productonpage, String type) {
		int n = count(id, type);
        int s;
        if (productonpage != -1) {
            s = n / productonpage;
            if (n % productonpage != 0) {
                s++;
            }
        }
        else
        {
            s=1;
        }
        
        return s;
	}
	
	@Transactional
	public int count(String id, String type) {
		Session session = sessionFactory.getCurrentSession();
		
        String hql = "from Products p where ";
        hql = addHql(type, hql);
        hql+= id;
        Query query = session.createQuery(hql);
        List<Products> ds = query.list();
        int sl = ds.size();
        return sl;
	}
	@Transactional
	private String addHql(String type, String hql) {
		if(type=="brand"){
			hql +="p.brand.brandid =" ;
		}
        else if(type=="catalog"){
        	hql +="p.productcatalog.catalogid =" ;
        }
		return hql;
		
	}
	@Transactional
	public List<Products> getProductList(String id, int productonpage,
			int page, int sortby, String type) {
		Session session = sessionFactory.getCurrentSession();
        int n = (page-1)*productonpage;
        int m = productonpage;
        String hql;
        hql = "from Products p where ";
        hql = addHql(type, hql);
        hql+= id;
        hql = addHqlSort(sortby, hql);
        
        Query query = session.createQuery(hql);
        if(productonpage != -1){
            query.setFirstResult(n);
            query.setMaxResults(m);
        }
        List<Products> listProduct = query.list();
        return listProduct;
	}
	
	private String addHqlSort(int sortby, String hql) {
		if(sortby ==-1)
        	hql+=" order by p.productname asc";
        if(sortby ==0)
        	hql+=" order by p.productname desc";
        if(sortby ==1)
        	hql+=" order by p.price asc";
        if(sortby ==2)
        	hql+=" order by p.price desc";
        if(sortby ==3)
        	hql+=" order by p.rating desc";
        return hql;
	}
	
}
